contents

๐Ÿ’ก ์ฝ”๋”ฉ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ๋น„ํŠธ ์—ฐ์‚ฐ(Bit Manipulation) ๊ฐ€์ด๋“œ ๋ฐ ์˜ˆ์ œ

๋น„ํŠธ ์—ฐ์‚ฐ์€ ๋น ๋ฅธ ๊ณ„์‚ฐ(O(1)), ๊ณต๊ฐ„ ์ ˆ์•ฝ, ํŠน์ˆ˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜/์ตœ์ ํ™”์—์„œ ๋งค์šฐ ์œ ์šฉํ•˜๋ฉฐ, ์ฝ”๋”ฉ ํ…Œ์ŠคํŠธ์™€ ๋ฉด์ ‘์—์„œ ์ž์ฃผ ์ถœ์ œ๋ฉ๋‹ˆ๋‹ค.


1. ๋น„ํŠธ ์—ฐ์‚ฐ์˜ ๊ธฐ๋ณธ ๊ฐœ๋…


2. ์ž์ฃผ ์“ฐ๋Š” ๋น„ํŠธ ์—ฐ์‚ฐ์ž

์—ฐ์‚ฐ์ž ๊ธฐํ˜ธ ๊ธฐ๋Šฅ ์˜ˆ์‹œ ๊ฒฐ๊ณผ
AND & ๋น„ํŠธ ๋‹จ์œ„ AND 5 & 3 โ†’ 0101 & 0011 0001(1)
OR | ๋น„ํŠธ ๋‹จ์œ„ OR 5 | 3 0111(7)
XOR ^ ๋น„ํŠธ ๋‹จ์œ„ XOR 5 ^ 3 0110(6)
NOT ~ ๋น„ํŠธ ๋ฐ˜์ „(๋ชจ๋“  ๋น„ํŠธ ๋’ค์ง‘์Œ) ~5 ...
์™ผ์ชฝ ์‹œํ”„ํŠธ << n๋งŒํผ ์™ผ์ชฝ ์ด๋™ 3 << 2 (0011โ†’1100) 12
์˜ค๋ฅธ์ชฝ ์‹œํ”„ํŠธ >> n๋งŒํผ ์˜ค๋ฅธ์ชฝ ์ด๋™ 8 >> 2 (1000โ†’0010) 2

3. ๋น„ํŠธ ์—ฐ์‚ฐ ๊ธฐ๋ณธ ํŠธ๋ฆญ

a. ํ™€์ˆ˜/์ง์ˆ˜ ํŒ๋ณ„

b. ๋‘ ์ˆ˜ ์Šค์™‘(XOR ์Šค์™‘)

a ^= b;
b ^= a;
a ^= b;

(์ž„์‹œ๋ณ€์ˆ˜ ์—†์ด ๊ฐ€๋Šฅ)

c. k๋ฒˆ์งธ ๋น„ํŠธ ์„ค์ •/ํ•ด์ œ/ํ† ๊ธ€


4. ๋น„ํŠธ ์นด์šดํŠธ ๋ฐ ์œ„์น˜ ํƒ์ƒ‰

a. ์„ค์ •๋œ ๋น„ํŠธ ๊ฐœ์ˆ˜ ์„ธ๊ธฐ(Kernighan ์•Œ๊ณ ๋ฆฌ์ฆ˜)

int countBits(int n) {
    int count = 0;
    while (n != 0) {
        n &= (n - 1);
        count++;
    }
    return count;
}

์„ค์ •๋œ ๋น„ํŠธ๋ฅผ ํ•˜๋‚˜์”ฉ ์ œ๊ฑฐ

b. k๋ฒˆ์งธ ๋น„ํŠธ ์ถ”์ถœ

int getKthBit(int n, int k) {
    return (n >> k) & 1;
}

c. ๊ฐ€์žฅ ๋‚ฎ์€ ์„ค์ • ๋น„ํŠธ ์ถ”์ถœ

int lowestBit = n & -n;

(์ตœํ•˜์œ„ 1๋น„ํŠธ๋งŒ ๋‚จ๊น€)


5. ๋น„ํŠธ๋งˆ์Šคํฌ(Bitmask)๋ฅผ ์ด์šฉํ•œ ๋ถ€๋ถ„์ง‘ํ•ฉ/์ƒํƒœ ํ‘œํ˜„

๋ถ€๋ถ„์ง‘ํ•ฉ ์ƒ์„ฑ ์˜ˆ์‹œ:

for (int mask = 0; mask < (1 << n); mask++) {
    for (int i = 0; i < n; i++) {
        if (((mask >> i) & 1) == 1) {
            // i๋ฒˆ์งธ ์›์†Œ ํฌํ•จ
        }
    }
}

6. ๋Œ€ํ‘œ ๋น„ํŠธ ๋ฌธ์ œ

a. ์ˆ˜์—ด์—์„œ ํ•œ ๋ฒˆ๋งŒ ๋‚˜ํƒ€๋‚˜๋Š” ์›์†Œ ์ฐพ๊ธฐ (Single Number)

int unique = 0;
for (int num : arr)
    unique ^= num;
return unique;

(XOR๋กœ ์ค‘๋ณต ์ œ๊ฑฐ, ๋‹จ์ผ ์›์†Œ๋งŒ ๋‚จ์Œ)

b. ํ™€์ˆ˜ ๋ฒˆ ๋“ฑ์žฅ ์›์†Œ ์ฐพ๊ธฐ

c. 2์˜ ๊ฑฐ๋“ญ์ œ๊ณฑ ํŒ๋ณ„

boolean isPowerOf2(int n) {
    return n > 0 && (n & (n - 1)) == 0;
}

(1๋น„ํŠธ๋งŒ ์„ค์ •๋œ ์ˆ˜)

d. Sieve(์—๋ผํ† ์Šคํ…Œ๋„ค์Šค ๋“ฑ)์— ๋น„ํŠธ๋งˆ์Šคํฌ ํ™œ์šฉ


7. ๋ฉด์ ‘/์ฝ”ํ…Œ์—์„œ์˜ ํŒจํ„ด๋ณ„ ํ™œ์šฉ

์ž‘์—… ๋Œ€ํ‘œ ๋น„ํŠธ ํŠธ๋ฆญ
๋ถ€๋ถ„์ง‘ํ•ฉยท์กฐํ•ฉ ์ƒ์„ฑ 0 ~ (2^n)-1 ๋น„ํŠธ๋งˆ์Šคํฌ ๋ฐ˜๋ณต
๋น ๋ฅธ ์ง‘ํ•ฉ ๋ฉค๋ฒ„์‹ญ ๋น„ํŠธ๋งˆ์Šคํฌ ํ™œ์šฉ (Set ํšจ๊ณผ)
์œ ์ผ๊ฐ’ยท๋นˆ๋„ ์นด์šดํŠธ XOR, ๋น„ํŠธ ์นด์šดํŠธ
๋น ๋ฅธ ์ˆ˜ํ•™์—ฐ์‚ฐ ์‹œํ”„ํŠธยทAND/OR๋กœ ๊ณฑ์…ˆยท๋‚˜๋ˆ—์…ˆ
DP/๊ฒŒ์ž„ ์ƒํƒœ ์••์ถ• ๋น„ํŠธ๋งˆ์Šคํฌ DP, ์ƒํƒœ ํ‘œํ˜„

8. ๊ณ ๊ธ‰ ๋น„ํŠธ ํŠธ๋ฆญ


9. ์‹ค์ˆ˜/์ฃผ์˜ ์‚ฌํ•ญ


10. ์š”์•ฝ ํ‘œ โ€“ ๋น„ํŠธ ์—ฐ์‚ฐ ์ฝ”๋”ฉ ์‹œํ—˜ ํŒจํ„ด

ํŒจํ„ด ์˜ˆ์‹œ ์ฝ”๋“œ/ํ‘œํ˜„
k๋ฒˆ์งธ ๋น„ํŠธ ์ฒดํฌ (n >> k) & 1
k๋ฒˆ์งธ ๋น„ํŠธ ์„ค์ • n
k๋ฒˆ์งธ ๋น„ํŠธ ํ•ด์ œ n &= ~(1 << k)
XOR ์Šค์™‘ a ^= b; b ^= a; a ^= b;
๋น„ํŠธ์นด์šดํŠธ while (n != 0) {n &= (n-1); count++;}
2์˜ ๊ฑฐ๋“ญ์ œ๊ณฑ ์ฒดํฌ n > 0 && (n & (n-1)) == 0
๋‹จ์ผ๊ฐ’ ์ฐพ๊ธฐ(XOR) ans ^= arr[i]
๋ถ€๋ถ„์ง‘ํ•ฉ ์—ด๊ฑฐ mask: 0 ~ (1<<n)-1

๐Ÿ’ก ๋น„ํŠธ ์—ฐ์‚ฐ ์ฝ”๋”ฉ ํ…Œ์ŠคํŠธ ๋Œ€ํ‘œ ๋นˆ์ถœ ๋ฌธ์ œ & ํ’€์ด/ํŠธ๋ฆญ ์ •๋ฆฌ

์•„๋ž˜๋Š” ์ฝ”๋”ฉ ํ…Œ์ŠคํŠธ์™€ ๋ฉด์ ‘์—์„œ ๊ฐ€์žฅ ์ž์ฃผ ์ถœ์ œ๋˜๋Š” ๋น„ํŠธ ์—ฐ์‚ฐ ๋ฌธ์ œ์™€ ๊ธฐ๋ณธ ์†”๋ฃจ์…˜ ๋ฐ ํ•ต์‹ฌ ์•„์ด๋””์–ด์ž…๋‹ˆ๋‹ค.


1. Single Number (ํ•œ ๋ฒˆ๋งŒ ๋“ฑ์žฅํ•˜๋Š” ์ˆ˜ ์ฐพ๊ธฐ)

๋ฌธ์ œ:
์ •์ˆ˜ ๋ฐฐ์—ด์—์„œ, ๋ชจ๋“  ์ˆซ์ž๊ฐ€ ๋‘ ๋ฒˆ์”ฉ ๋“ฑ์žฅํ•˜์ง€๋งŒ ์˜ค์ง ํ•˜๋‚˜๋งŒ ํ•œ ๋ฒˆ๋งŒ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์ˆซ์ž๋ฅผ ์ฐพ์œผ์„ธ์š”.

ํ’€์ด:
๋ชจ๋“  ์ˆซ์ž๋ฅผ XORํ•˜๋ฉด, ์ง์ˆ˜ ๊ฐœ๋Š” ์†Œ๊ฑฐ๋˜์–ด ๋‹จ์ผ ์ˆซ์ž๋งŒ ๋‚จ์Œ.

int singleNumber(int[] nums) {
    int res = 0;
    for (int num : nums) res ^= num;
    return res;
}

2. Two Single Numbers (๋‘ ๋ฒˆ ๋“ฑ์žฅํ•˜์ง€ ์•Š๋Š” ์ˆ˜ 2๊ฐœ ์ฐพ๊ธฐ)

๋ฌธ์ œ:
๋ฐฐ์—ด์— ํ•œ ๋ฒˆ๋งŒ ๋“ฑ์žฅํ•˜๋Š” ์ˆ˜๊ฐ€ ์ •ํ™•ํžˆ 2๊ฐœ, ๋‚˜๋จธ์ง€๋Š” ๋ชจ๋‘ ๋‘ ๋ฒˆ์”ฉ. ๋‘˜ ๋‹ค ์ฐพ์•„๋ณด์„ธ์š”.

ํ’€์ด:
์ „์ฒด XORํ•˜๋ฉด x^y๊ฐ€ ๋‚˜์˜ด. ์˜ค๋ฅธ์ชฝ ์ฒซ 1๋น„ํŠธ๋กœ ๊ทธ๋ฃน์„ ๋‚˜๋ˆ  ๋‹ค์‹œ XOR.

int xor = 0;
for (int num : nums) xor ^= num;
int mask = xor & -xor;
int x = 0, y = 0;
for (int num : nums) {
    if ((num & mask) == 0) x ^= num;
    else y ^= num;
}
// x์™€ y๊ฐ€ ๋‹ต

3. 1 ๋น„ํŠธ ๊ฐœ์ˆ˜ ์„ธ๊ธฐ (Hamming Weight)

๋ฌธ์ œ:
์ •์ˆ˜ ์ด์ง„์ˆ˜ ํ‘œํ˜„์—์„œ 1์˜ ๊ฐœ์ˆ˜๋ฅผ ์„ธ์–ด๋ผ.

ํ’€์ด:
Brian Kernighan ์•Œ๊ณ ๋ฆฌ์ฆ˜

int hammingWeight(int n) {
    int count = 0;
    while (n != 0) {
        n &= (n - 1);
        count++;
    }
    return count;
}

4. 2์˜ ๊ฑฐ๋“ญ์ œ๊ณฑ ํŒ๋ณ„

๋ฌธ์ œ:
์ •์ˆ˜๊ฐ€ 2์˜ ๊ฑฐ๋“ญ์ œ๊ณฑ์ธ์ง€ ์ฒดํฌํ•˜์„ธ์š” (๋‹จ ํ•˜๋‚˜์˜ 1๋น„ํŠธ).

ํ’€์ด:

boolean isPowerOfTwo(int n) {
    return n > 0 && (n & (n - 1)) == 0;
}

5. ๋ถ€๋ถ„์ง‘ํ•ฉ ์ƒ์„ฑ(Bitmask ํ™œ์šฉ)

๋ฌธ์ œ:
์ฃผ์–ด์ง„ ์ง‘ํ•ฉ์˜ ๋ชจ๋“  ๋ถ€๋ถ„์ง‘ํ•ฉ์„ ์ถœ๋ ฅํ•˜์„ธ์š”.

ํ’€์ด:

for (int mask = 0; mask < (1 << n); mask++) {
    for (int i = 0; i < n; i++) {
        if ((mask & (1 << i)) != 0) {
            // i๋ฒˆ์งธ ์š”์†Œ ํฌํ•จ
        }
    }
}

6. Missing Number (0~n, ํ•˜๋‚˜๋งŒ ์—†๋Š” ์ˆ˜ ์ฐพ๊ธฐ)

๋ฌธ์ œ:
0~n๊นŒ์ง€์˜ ์ˆ˜๊ฐ€ ํ•˜๋‚˜๋งŒ ๋น ์ง„ ๋ฐฐ์—ด์—์„œ, ๋น ์ง„ ์ˆซ์ž๋ฅผ ์ฐพ์œผ์„ธ์š”.

ํ’€์ด:
๋ฐฐ์—ด ์ „์ฒด XOR + ์ธ๋ฑ์Šค XOR + n ๊ฐ’ โ‡’ ์ •๋‹ต

int missingNumber(int[] nums) {
    int res = 0;
    int n = nums.length;
    for (int i = 0; i < n; i++) res ^= nums[i] ^ i;
    return res ^ n;
}

7. ๋น„ํŠธ ๋’ค์ง‘๊ธฐ (Reverse Bits)

๋ฌธ์ œ:
32๋น„ํŠธ ์ˆซ์ž์˜ ๋น„ํŠธ ์ˆœ์„œ๋ฅผ ๋ฐ˜์ „ํ•˜์„ธ์š”.

ํ’€์ด:

int reverseBits(int n) {
    int res = 0;
    for (int i = 0; i < 32; i++) {
        res = (res << 1) | (n & 1);
        n >>= 1;
    }
    return res;
}

8. ๋‘ ์ˆ˜ ์Šค์™‘ (๋น„ํŠธ๋งŒ์œผ๋กœ ์ž„์‹œ ์—†์ด ๊ตํ™˜)

๋ฌธ์ œ:
a์™€ b๋ฅผ ์ž„์‹œ ๋ณ€์ˆ˜ ์—†์ด ์Šค์™‘ํ•˜์„ธ์š”.

ํ’€์ด:

a ^= b; b ^= a; a ^= b;

9. k๋ฒˆ์งธ ๋น„ํŠธ Setting/Clearing/Toggling

๋ฌธ์ œ:
์ •์ˆ˜ n์—์„œ k๋ฒˆ์งธ ๋น„ํŠธ๋ฅผ ์„ค์ •/ํ•ด์ œ/ํ† ๊ธ€ํ•˜์„ธ์š”.

ํ’€์ด:

// ์„ค์ •
n |= (1 << k);
// ํ•ด์ œ
n &= ~(1 << k);
// ํ† ๊ธ€
n ^= (1 << k);

์š”์•ฝ ํ‘œ

๋ฌธ์ œ ์œ ํ˜• ํ•ต์‹ฌ ๋น„ํŠธ ํŠธ๋ฆญ/์ฝ”๋“œ
๋‹จ์ผ๊ฐ’ ์ฐพ๊ธฐ XOR ์ „์ฒด
๋‘ ๋‹จ์ผ๊ฐ’ ์ฐพ๊ธฐ XORโ†’๋งˆ์Šคํฌ๋กœ ๊ทธ๋ฃน ๋ถ„๋ฆฌ
1 ๋น„ํŠธ ๊ฐœ์ˆ˜ n &= (n-1) ๋ฐ˜๋ณต
2์˜ ๊ฑฐ๋“ญ์ œ๊ณฑ ํŒ๋ณ„ n > 0 && (n & (n-1)) == 0
๋ถ€๋ถ„์ง‘ํ•ฉ ์ƒ์„ฑ mask: 0 ~ (1<<n)-1
๋น ์ง„ ์ˆซ์ž ์ฐพ๊ธฐ XOR(index+๋ฐฐ์—ด+n)
๋น„ํŠธ ๋’ค์ง‘๊ธฐ shift+OR ๋ฐ˜๋ณต
Swap ๋ฌด์ž„์‹œ a ^= b โ†’ b ^= a โ†’ a ^= b
๋น„ํŠธ ์„ค์ •/ํ•ด์ œ/ํ† ๊ธ€ n

references